package cn.zhxu.pack;

import cn.zhxu.xjson.JsonKit;
import com.jfinal.kit.StrKit;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class App {


    public static void main(String[] args) throws Exception {
        long startTime = System.currentTimeMillis();
        Config conf = Config.me();
        File inputFile = new File(conf.getInputPath());
        File outputFile = new File(conf.getOutputPath());
        File configFile = new File(conf.getConfigPath());
        checkConfigAndInputFiles(configFile, inputFile);
        Map<String, Object> trackData = null;
        if (conf.isIncremental()) {
            File trackFile = new File(conf.getIncTrackPath());
            if (trackFile.exists()) {
                trackData = toTrackData(trackFile);
            }
            if (trackData == null) {
                trackData = new HashMap<>();
            }
        } else if (outputFile.exists() && !deleteBuildDir(outputFile)) {
            System.out.println("can not delete the build dir: " + outputFile);
            return;
        }
        int count = 0;
        String outputBasePath = outputFile.getPath();
        if (configFile.isDirectory()) {
            File[] files = configFile.listFiles();
            if (files == null) {
                System.out.println("未读取到配置文件!");
                return;
            }
            for (File file : files) {
                if (file.getName().endsWith(conf.getConfExtName())) {
                    count += doPack(file, inputFile, outputBasePath, trackData);
                }
            }
        } else if (configFile.getName().endsWith(conf.getConfExtName())) {
            count += doPack(configFile, inputFile, outputBasePath, trackData);
        } else {
            System.out.println("未读取到配置文件!");
        }
        if (conf.isIncremental()) {
            saveTrackJsonToFile(trackData, conf.getIncTrackPath());
        }
        long time = System.currentTimeMillis() - startTime;
        System.out.println("Total " + count + " projects packed, Time: " + (time / 1000f) + " Seconds");
    }

    private static void saveTrackJsonToFile(Map<String, Object> trackData, String filePath) throws IOException {
        File trackFile = new File(filePath);
        if (!trackFile.exists()) {
            trackFile.createNewFile();
        }
        FileWriter writer = new FileWriter(trackFile, false);
        writer.write(JsonKit.toPretty(trackData));
        writer.close();
    }

    private static Map<String, Object> toTrackData(File file) {
        try {
            return new HashMap<>(JsonKit.toMapper(Utils.fileToString(file)).toMap());
        } catch (Exception e) {
            return null;
        }
    }

    private static boolean deleteBuildDir(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            assert files != null;
            String theConfig = Config.me().getTheConfig();
            for (File f: files) {
                String fName = f.getName();
                if (Config.E_PACK_SETTINGS.equals(fName)) {
                    continue;
                }
                if (StrKit.isBlank(theConfig) || fName.equals(theConfig)) {
                    if (!deleteFile(f)) {
                        return false;
                    }
                }
            }
            return true;
        } else {
            return deleteFile(file);
        }
    }

    private static boolean deleteFile(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            assert files != null;
            for (File f: files) {
                if (!deleteFile(f)) {
                    System.out.println("can not delete " + f);
                    return false;
                }
            }
            return true;
        } else {
            return file.delete();
        }
    }


    private static int doPack(File configFile, File inputFile, String outputBasePath, Map<String, Object> trackData) throws Exception {
        Config conf = Config.me();
        Properties data = new Properties();
        data.load(new FileReader(configFile));
        String configName = configFile.getName();
        configName = configName.substring(0, configName.length() - conf.getConfExtName().length());
        String theConfig = conf.getTheConfig();
        if (StrKit.notBlank(theConfig) && !theConfig.equals(configName)) {
            System.out.println(configName + ": skiped");
            System.out.println();
            return 0;
        }
        Map<String, Object> theTrackData = null;
        if (trackData != null) {
            theTrackData = (Map<String, Object>) trackData.get(configName);
            if (theTrackData == null) {
                theTrackData = new HashMap<>();
                trackData.put(configName, theTrackData);
            }
        }
        System.out.println(configName + ": packing");
        int count = new Packer(configName, outputBasePath, data, theTrackData).doPack(inputFile);
        System.out.println(configName + ": " + count + " files packed");
        System.out.println();
        return 1;
    }

    private static void checkConfigAndInputFiles(File configFile, File inputFile) {
        if (!configFile.exists()) {
            System.err.println("配置路径[" + configFile + "]不存在!");
            System.exit(1);
        }
        if (!inputFile.exists()) {
            System.err.println("输入路径[" + inputFile + "]不存在!");
            System.exit(1);
        }
    }

}
